
#ifndef COMPONENT_H
#define COMPONENT_H

#include <pcl/io/pcd_io.h>
#include <pcl/common/transforms.h>
#include <pcl/sample_consensus/ransac.h>
#include <pcl/sample_consensus/sac_model_plane.h>
#include <pcl/features/normal_3d_omp.h>
#include <pcl/common/transforms.h>
#include <pcl/common/centroid.h>
#include <algorithm>

/*!
 \file component.h This file contains the component class.
 \author Sqizzato Stefano
 \author Maroso Alessandro

*/

using namespace std;
using namespace pcl;

/*!
 \brief The class representing a component.
 \author Sqizzato Stefano
 \author Maroso Alessandro

*/
class Component
{
public:

//CONSTRUCTORS
    /*!
     \brief Empty constructor.

    */
    Component();
    /*!
     \brief Constructor for target components.

     \param[in] cloud_ The cloud containing the component.
     \param[in] componentIndices_ The indices of the component.
     \param[in] generatingIndex_ The index of the point which generated the component in the component selection.
     \param[in] clusterThreshold_ The clusterization threshold used in the component selection.
     \param[in] colorThreshold_ The color threshold used in the component selection.
     \param[in] skinThickness_ The skin thickness used in the component shape matching.
    */
    Component(PointCloud<PointXYZRGB>::Ptr cloud_, PointIndices::Ptr componentIndices_, int generatingIndex_, double clusterThreshold_, int colorThreshold_, double skinThickness_);
    /*!
     \brief Constructor for the source components.

     \param[in] cloud_ The cloud containing the component.
     \param[in] componentIndices_ The indices of the component.
    */
    Component(PointCloud<PointXYZRGB>::Ptr cloud_, PointIndices::Ptr componentIndices_);

//GETTERS
    /*!
     \brief Gets the component cloud to which the component is referred (target or source).

     \return PointCloud<PointXYZRGB> The component cloud to which the component is referred (target or source).
    */
    PointCloud<PointXYZRGB>::Ptr getCloud();
    /*!
     \brief Gets the component's pointIndices.

     \return PointIndices::Ptr The component's pointIndices.
    */
    PointIndices::Ptr getIndices();
    /*!
     \brief Gets the component's point cloud.

     \return PointCloud<PointXYZRGB> The component's point cloud.
    */
    PointCloud<PointXYZRGB>::Ptr getComponentCloud();
    /*!
     \brief Gets the index of the point clicked on the target/source cloud to segment this component.

     \return int The index of the point clicked on the target/source cloud to segment this component.
    */
    int getGeneratingIndex();
    /*!
     \brief Gets the color threshold used to segment this component.

     \return int The color threshold used to segment this component.
    */
    int getColorThreshold();
    /*!
     \brief Gets the clustering threshold used tosegment this component.

     \return double The clustering threshold used tosegment this component.
    */
    double getClusterThreshold();
    /*!
     \brief Gets the skin thickness to use for t he shape matching.

     \return double The skin thickness to use for t he shape matching.
    */
    double getSkinThickness();
    /*!
     \brief Gets the R value of the color of the generating point

     \return int The R value of the color of the generating point
    */
    int getColR();
    /*!
     \brief Gets the G value of the color of the generating point

     \return int The G value of the color of the generating point
    */
    int getColG();
    /*!
     \brief Gets the B value of the color of the generating point

     \return int The B value of the color of the generating point
    */
    int getColB();
    /*!
     \brief Gets the X coordinate of the generating point

     \return float The X coordinate of the generating point
    */
    float getPosX();
    /*!
     \brief Gets the Y coordinate of the generating point

     \return float The Y coordinate of the generating point
    */
    float getPosY();
    /*!
     \brief Gets the Z coordinate of the generating point

     \return float The Z coordinate of the generating point
    */
    float getPosZ();
    /*!
     \brief Gets the size of the component's pointIndices vector.

     \return int The size of the component's pointIndices vector.
    */
    int getSize();
    /*!
     \brief Gets the average color of the points of the cloud in HSV (RGB for now)

     \return Eigen::Vector3f  The average color of the points of the cloud in HSV (RGB for now)
    */
    Eigen::Vector3f getAverageColor();
    /*!
     \brief Gets the approximation of the center of mass of the component

     \return PointXYZRGB The approximation of the center of mass of the component
    */
    PointXYZRGB getCenterOfMass();
    /*!
     \brief Gets the 4f vector representing the plane normal and it's distance from origin.

     \return Eigen::VectorXf  The 4f vector representing the plane normal and it's distance from origin.
    */
    Eigen::VectorXf getPlaneCoefficients ();
    /*!
     \brief Gets the value of the estimated radius of the component from the center of mass

     \return float The value of the estimated radius of the component from the center of mass
    */
    float getRadiusToCenterOfMass();
    /*!
     \brief Gets the average height of the component

     \return float The average height of the component
    */
    float getAverageHeight();

private:
    PointCloud<PointXYZRGB>::Ptr cloud; /*!< Pointer to the cloud from which the component was segmented.*/
    PointIndices::Ptr componentIndices; /*!< Indices of the component's points referred to "cloud" point cloud.*/
    int generatingIndex; /*!< Index of the point clicked on the target cloud to segment this component.*/
    double clusterThreshold; /*!< Clustering threshold used tosegment this component. */
    int colorThreshold; /*!< Color threshold used to segment this component. */
    double skinThickness; /*!< Skin thickness to use for the shape component matching. */
};
#endif // COMPONENT_H
